package com.zmc.product.application.impl;

import com.zmc.common.annotation.PreventRepeatSubmit;
import com.zmc.common.constant.CacheConstants;
import com.zmc.common.domain.es.EsSkuAttr;
import com.zmc.common.domain.es.EsSkuEntity;
import com.zmc.common.domain.freight.FreightQueryPrice;
import com.zmc.common.domain.good.GoodSkuBuyDetail;
import com.zmc.common.domain.resp.product.ProductInventoryResp;
import com.zmc.common.domain.vo.good.GoodsDeleteVo;
import com.zmc.common.domain.vo.good.GoodsInventoryVo;
import com.zmc.common.domain.vo.good.GoodsUpVo;
import com.zmc.common.domain.query.coupon.CouponFeignQuery;
import com.zmc.common.domain.query.goods.GoodDetailFeignQuery;
import com.zmc.common.domain.resp.coupon.CouponAllFeignResp;
import com.zmc.common.enums.RequestSourceEnum;
import com.zmc.common.exception.base.BusinessException;
import com.zmc.common.utils.uuid.SnowflakeIdUtils;
import com.zmc.product.infrastructure.enums.ProductPictureEnum;
import com.zmc.product.infrastructure.enums.ProductStatusEnum;
import com.zmc.common.utils.JsonUtils;
import com.zmc.common.utils.redis.RedisCache;
import com.zmc.product.exception.ProductNotExistException;
import com.zmc.product.exception.ProductSkuException;
import com.zmc.product.exception.ProductStatusException;
import com.zmc.common.utils.token.AuthTokenService;
import com.zmc.product.application.GoodsApplicationService;
import com.zmc.product.feign.CouponFeignService;
import com.zmc.product.infrastructure.constant.ProductApproveConstant;
import com.zmc.product.infrastructure.bean.vo.*;
import com.zmc.product.infrastructure.entity.*;
import com.zmc.product.infrastructure.service.*;
import com.zmc.product.infrastructure.bean.query.GoodsDetailQuery;
import com.zmc.product.infrastructure.bean.response.GoodsDetailResp;
import com.zmc.product.feign.SearchFeignService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author：zmc
 * @Date：2024/11/1 9:36
 */

@Component
public class GoodsApplicationServiceImpl implements GoodsApplicationService {

    public static Logger log = LoggerFactory.getLogger(GoodsApplicationServiceImpl.class);


    @Autowired
    private CommodityCategoryService commodityCategoryService;

    @Autowired
    private CommodityGoodsService commodityGoodsService;

    @Autowired
    private CommodityGoodsDetailService commodityGoodsDetailService;

    @Autowired
    private CommodityGoodsDetailPictureService commodityGoodsDetailPictureService;

    @Autowired
    private CommodityCategoryPropertyValueService commodityCategoryPropertyValueService;

    @Autowired
    private CommodityGoodsSkuService commodityGoodsSkuService;

    @Autowired
    private AuthTokenService authTokenService;

    @Autowired
    private SearchFeignService searchFeignService;

    @Autowired
    private CouponFeignService couponFeignService;

    @Autowired
    private CommodityGoodsDetailService goodsDetailService;

    @Autowired
    private CommodityGoodsDetailPictureService detailPictureService;

    @Autowired
    private CommodityGoodsPropertyValueService goodsPropertyValueService;

    @Autowired
    private CommodityBrandService brandService;

    @Autowired
    private InventoryGoodsStockService inventoryGoodsStockService;

    @Autowired
    private RedisCache redisCache;


    //todo
    public static String upLoadPrefix = "http://localhost:8080/api";

    @Override
    public GoodsDetailResp getGoodsDetail(GoodsDetailQuery query) {
        //1、从es中取出商品详情信息
        GoodDetailFeignQuery goodDetailFeignQuery = new GoodDetailFeignQuery();
        goodDetailFeignQuery.setSpuId(query.getSpuId());
        List<EsSkuEntity> skuList = JsonUtils.transToArrayClass(searchFeignService.getGoodsDetailBySpuId(goodDetailFeignQuery), EsSkuEntity.class);
        if (CollectionUtils.isEmpty(skuList)) {
            log.error("商品不存在或商品没有上架, goodsId:{}", query.getSpuId());
            throw new ProductNotExistException();
        }
        EsSkuEntity skuEntity = skuList.get(0);
        GoodsDetailResp resp = new GoodsDetailResp();
        resp.setSpuId(query.getSkuId());
        resp.setName(skuEntity.spuTitle);
        resp.setSubName(skuEntity.getSpuSubTitle());
        resp.setBrandName(skuEntity.brandName);
        //获取优惠信息
        CouponFeignQuery couponFeignQuery = new CouponFeignQuery();
        List<String> skuIds = skuList.stream().map(EsSkuEntity::getSkuId).collect(Collectors.toList());
        couponFeignQuery.setType(1);
        couponFeignQuery.setSkuIds(skuIds);
        List<CouponAllFeignResp> couponList = JsonUtils.transToArrayClass(couponFeignService.getCouponDetail(couponFeignQuery), CouponAllFeignResp.class);
        //sku集合
        List<SkuVo> skuVoList = new ArrayList<>();
        for (EsSkuEntity sku : skuList) {
            SkuVo skuVo = new SkuVo();
            skuVo.setSkuId(sku.getSkuId());
            skuVo.setPrice(sku.getSkuPrice());
            //缩小图片
            skuVo.setPicture(upLoadPrefix + sku.getSkuImg());
            skuVo.setSaleValue(sku.getAttrs().stream().map(EsSkuAttr::getPropertyValue).collect(Collectors.joining(" ")));
            skuVo.setInventory(sku.getSaleCount());
            couponList.stream().filter(item -> item.getSkuId().equals(sku.getSkuId())).findFirst().ifPresent(item -> {
                skuVo.setCoupon(item.getCoupon());
                skuVo.setLadder(item.getLadder());
                skuVo.setReduction(item.getReduction());
            });
            skuVoList.add(skuVo);
        }
        resp.setSkus(skuVoList);
        //商品详情信息
        CommodityGoodsDetailEntity detailEntity = commodityGoodsDetailService.getBySpuId(query.getSpuId());
        if (detailEntity == null) {
            log.error("商品详情不存在, spuId:{}", query.getSpuId());
            throw new ProductNotExistException();
        }
        resp.setServicePromise(detailEntity.getServiceGuarantees());
        resp.setPackageList(detailEntity.getPackageList());
        List<CommodityGoodsDetailPictureEntity> pictures = commodityGoodsDetailPictureService.getPicturesBySpuId(query.getSpuId());
        //todo 后面会统一替换为阿里云oss
        Map<String, List<String>> pictureMap = pictures.stream().collect(Collectors.groupingBy(CommodityGoodsDetailPictureEntity::getType, Collectors.mapping(item -> {
            return upLoadPrefix + item.getPicturePath();
        }, Collectors.toList())));
        resp.setMainPictures(pictureMap.get(ProductPictureEnum.PRODUCT_DETAIL.getCode()));
        resp.setIntroducePicture(pictureMap.get(ProductPictureEnum.PRODUCT_INTRODUCE.getCode()));
        //获取商品规格列表(基础信息)
        BasePropertyValueDetailVo detail = new BasePropertyValueDetailVo();
        List<BasePropertyValueVo> baseInfoList = commodityCategoryPropertyValueService.getGoodsBaseInfoBySpuId(query.getSpuId());
        LinkedHashMap<String, List<BasePropertyValueVo>> baseInfoMap = baseInfoList.stream().collect(Collectors.groupingBy(BasePropertyValueVo::getName, LinkedHashMap::new, Collectors.toList()));
        detail.setBaseInfo(baseInfoMap);
        resp.setDetails(detail);
        //是否收藏
        resp.setIsCollection(redisCache.getCacheMapValue(CacheConstants.COLLECTION_KEY + authTokenService.getMemberInfo().getMemberId(), query.getSpuId()) != null ? 1 : 0);
        return resp;
    }

    @Override
    @Transactional
    public void submit(GoodsApproveVo approveVo) {
        CommodityGoodsEntity goodsEntity = commodityGoodsService.getById(approveVo.getId());
        ////非编辑状态不参与审核
        if (ProductStatusEnum.PRODUCT_AUDIT.getCode() != goodsEntity.getStatus() && ProductStatusEnum.PRODUCT_AUDIT_REJECT.getCode() != goodsEntity.getStatus()) {
            log.error("当前商品 goodsId:{},状态为 status:{},无法进行提审", approveVo.getId(), goodsEntity.getStatus());
            throw new ProductStatusException();
        }
        //审核拒绝
        if (ProductApproveConstant.PRODUCT_REJECT.equals(approveVo.getResult())) {
            goodsEntity.setStatus(ProductStatusEnum.PRODUCT_AUDIT_REJECT.getCode());
            commodityGoodsService.updateById(goodsEntity);
            return;
        }
        goodsEntity.setStatus(ProductStatusEnum.PRODUCT_AUDITING.getCode());
        goodsEntity.setUpdateBy(authTokenService.getUserInfo().getUsername());
        commodityGoodsService.updateById(goodsEntity);
        //提审事务完成后，删除es中sku数据，等待审核结果
        GoodDetailFeignQuery query = new GoodDetailFeignQuery();
        query.setSpuId(goodsEntity.getSpuId());
        List<EsSkuEntity> list = JsonUtils.transToArrayClass(searchFeignService.getGoodsDetailBySpuId(query), EsSkuEntity.class);
        if (CollectionUtils.isEmpty(list)){
            return;
        }
        //提审成功，商品进行审核，原有商品下架处理，等待审核结果
        GoodsDeleteVo goodsDeleteVo = new GoodsDeleteVo();
        goodsDeleteVo.setSpuId(goodsEntity.getSpuId());
        searchFeignService.productDelete(goodsDeleteVo).valid();
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void audit(GoodsApproveVo approveVo) {
        CommodityGoodsEntity goodsEntity = commodityGoodsService.getById(approveVo.getId());
        ////非审核中状态不能审核
        if (ProductStatusEnum.PRODUCT_AUDITING.getCode() != goodsEntity.getStatus()) {
            log.error("当前商品 goodsId:{},状态为 status:{},无法进行提审", approveVo.getId(), goodsEntity.getStatus());
            throw new ProductStatusException();
        }
        //审核拒绝
        if (ProductApproveConstant.PRODUCT_REJECT.equals(approveVo.getResult())) {
            goodsEntity.setStatus(ProductStatusEnum.PRODUCT_AUDIT_REJECT.getCode());
            commodityGoodsService.updateById(goodsEntity);
            return;
        }
        //审核通过，但是没有设置sku（机审）
        List<CommodityGoodsSkuEntity> skus = commodityGoodsSkuService.getBySpuId(goodsEntity.getSpuId());
        if (CollectionUtils.isEmpty(skus)) {
            log.error("当前商品 goodsId:{},没有设置sku", approveVo.getId());
            throw new ProductSkuException();
        }
        //审核通过，查看是否有库存，若存在库存，上架商品
        GoodsInventoryVo vo = new GoodsInventoryVo();
        List<String> skuIds = skus.stream().map(CommodityGoodsSkuEntity::getSkuId).collect(Collectors.toList());
        vo.setSkuIds(skuIds);
        List<ProductInventoryResp> respList = inventoryGoodsStockService.check(vo);
        if (!CollectionUtils.isEmpty(respList)) {
            List<GoodsUpVo> upVos = respList.stream().map(item -> {
                return new GoodsUpVo(item.getSkuId(), item.getSaleStockQuantity());
            }).collect(Collectors.toList());
            goodsEntity.setStatus(ProductStatusEnum.PRODUCT_HAS_LIST.getCode());
            //商品上架到es
            upGoods(upVos);
        } else {
            goodsEntity.setStatus(ProductStatusEnum.PRODUCT_WAIT_LIST.getCode());
        }
        goodsEntity.setUpdateBy(authTokenService.getUserInfo().getUsername());
        commodityGoodsService.updateById(goodsEntity);

    }

    @Override
    @Transactional
    public void upGoods(List<GoodsUpVo> list) {
        List<String> skuIds = list.stream().map(GoodsUpVo::getSkuId).collect(Collectors.toList());
        String merchantId = authTokenService.getUserInfo().getMerchantId();
        //1、提取数据
        List<GoodsEsVo> skuList = commodityGoodsSkuService.getBySkuIds(skuIds);;
        List<CommodityGoodsEntity> goodsList = new ArrayList<>();
        //2、将没有上架的商品进行上架到es，同时更新mysql商品状态为上架
        List<EsSkuEntity> esSkuEntityList = skuList.stream()
                .filter(item -> ProductStatusEnum.PRODUCT_HAS_LIST.getCode() != item.getStatus())
                //组装数据
                .map(item -> {
                    EsSkuEntity sku = new EsSkuEntity();
                    BeanUtils.copyProperties(item, sku);
                    List<EsSkuAttr> collect = Arrays.stream(item.getAttr().split(",")).map(s -> {
                        String[] split = s.split(":");
                        EsSkuAttr attr = new EsSkuAttr();
                        attr.setPropertyName(split[0]);
                        attr.setPropertyValue(split[1]);
                        CommodityGoodsEntity goodsEntity = new CommodityGoodsEntity();
                        goodsEntity.setSpuId(sku.getSpuId());
                        goodsEntity.setStatus(ProductStatusEnum.PRODUCT_HAS_LIST.getCode());
                        goodsList.add(goodsEntity);
                        return attr;
                    }).collect(Collectors.toList());
                    sku.setAttrs(collect);
                    sku.setHasStock(true);
                    sku.setMerchantId(merchantId);
                    return sku;
                }).collect(Collectors.toList());
        //3、更新mysql数据
        commodityGoodsService.updateBatchById(goodsList);
        //5、批量上架商品到es
        if (!CollectionUtils.isEmpty(esSkuEntityList)) {
            searchFeignService.productUpToEs(esSkuEntityList).valid();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @PreventRepeatSubmit(lockByPerson = true, source = RequestSourceEnum.MANAGE)
    public void saveGood(GoodSpuVo vo) {
        CommodityCategoryEntity category = commodityCategoryService.getById(vo.getCategoryId());
        if (category == null || category.getLevel() != 3) {
            throw new BusinessException("请选择叶子类目");
        }
        Integer skuLimit = category.getSkuLimit();
        String merchantId = authTokenService.getUserInfo().getMerchantId();
        Long count = commodityGoodsService.countByMerchantId(merchantId);
        if (count >= skuLimit) {
            throw new BusinessException("已超过spu阈值设置，无法添加");
        }
        //1、保存商品基础信息
        CommodityGoodsEntity goods = getGoodsEntity(vo);
        goods.setMerchantId(merchantId);
        goods.setSpuId(SnowflakeIdUtils.nextSnowFlackId(authTokenService.getUserInfo().getPhone()));
        commodityGoodsService.save(goods);
        //2、保存商品详情
        CommodityGoodsDetailEntity detail = new CommodityGoodsDetailEntity();
        detail.setSpuId(goods.getSpuId());
        detail.setDetailContent(vo.getDetailContent());
        detail.setServiceGuarantees(vo.getServiceGuarantees());
        detail.setPackageList(vo.getPackageList());
        goodsDetailService.save(detail);
        //3、保存商品图片
        detailPictureService.savePictures(vo.getPicture1(), vo.getPicture2(), goods.getSpuId());
        //4、保存基础属性
        goodsPropertyValueService.savePropertyValues(vo.getCategoryId(), vo.getSpuList(), goods.getSpuId());
    }

    @Override
    public GoodSpuVo getGoodInfo(Long id) {
        GoodSpuVo vo = new GoodSpuVo();
        //1、设置基础信息
        CommodityGoodsEntity goodsEntity = commodityGoodsService.getById(id);
        vo.setId(id);
        vo.setName(goodsEntity.getName());
        vo.setSubName(goodsEntity.getSubName());
        vo.setCategoryId(goodsEntity.getCategoryId());
        vo.setBrandId(goodsEntity.getBrandId());
        CommodityBrandEntity brand = brandService.getById(goodsEntity.getBrandId());
        vo.setBrandName(brand.getChineseName());
        vo.setGrossWeight(goodsEntity.getGrossWeight());
        vo.setLength(goodsEntity.getLength());
        vo.setWidth(goodsEntity.getWidth());
        vo.setHeight(goodsEntity.getHeight());
        vo.setStatus(goodsEntity.getStatus());
        //2、设置图片
        CommodityGoodsDetailEntity goodsDetailEntity = goodsDetailService.getBySpuId(goodsEntity.getSpuId());
        vo.setPackageList(goodsDetailEntity.getPackageList());
        vo.setServiceGuarantees(goodsDetailEntity.getServiceGuarantees());
        vo.setDetailContent(goodsDetailEntity.getDetailContent());
        List<CommodityGoodsDetailPictureEntity> pictures = detailPictureService.getPicturesBySpuId(goodsEntity.getSpuId());
        //2.1、商品详情图
        vo.setPicture1(pictures.stream().filter(pic -> ProductPictureEnum.PRODUCT_DETAIL.getCode().equals(pic.getType())).map(CommodityGoodsDetailPictureEntity::getPicturePath).collect(Collectors.joining(",")));
        //2.2、图文介绍
        vo.setPicture2(pictures.stream().filter(pic -> ProductPictureEnum.PRODUCT_INTRODUCE.getCode().equals(pic.getType())).map(CommodityGoodsDetailPictureEntity::getPicturePath).collect(Collectors.joining(",")));
        //3、设置基础属性设置
        vo.setSpuList(goodsPropertyValueService.setPropertyValue(goodsEntity.getSpuId(), vo.getCategoryId()));
        return vo;
    }

    @Override
    @Transactional
    @PreventRepeatSubmit(lockByPerson = true, source = RequestSourceEnum.MANAGE)
    public void updateGood(GoodSpuVo vo) {
        CommodityGoodsEntity goodsEntity = commodityGoodsService.getById(vo.getId());
        //1、更新商品基础信息
        CommodityGoodsEntity goods = getGoodsEntity(vo);
        goods.setId(vo.getId());
        //2、更新商品详情
        CommodityGoodsDetailEntity detail = goodsDetailService.getBySpuId(goodsEntity.getSpuId());
        detail.setDetailContent(vo.getDetailContent());
        detail.setServiceGuarantees(vo.getServiceGuarantees());
        detail.setPackageList(vo.getPackageList());
        goodsDetailService.updateById(detail);
        //3、更新商品图片
        //3-1 删除旧图片
        detailPictureService.removeBySpuId(goodsEntity.getSpuId());
        //3-2 保存新图片
        detailPictureService.savePictures(vo.getPicture1(), vo.getPicture2(), goodsEntity.getSpuId());
        //4、更新基础属性
        //4-1 删除旧属性信息
        goodsPropertyValueService.removeBySpuId(goodsEntity.getSpuId());
        //4-2 保存属性信息
        goodsPropertyValueService.savePropertyValues(vo.getCategoryId(), vo.getSpuList(), goodsEntity.getSpuId());
        //5-1、当商品有改动，商品必须待审
        goods.setStatus(ProductStatusEnum.PRODUCT_AUDIT.getCode());
        commodityGoodsService.updateById(goods);
    }

    @Override
    @Transactional
    public void remove(Long id) {
        CommodityGoodsEntity goodsEntity = commodityGoodsService.getById(id);
        commodityGoodsSkuService.removeBySpuId(goodsEntity.getSpuId());
        commodityGoodsService.removeById(goodsEntity.getId());
        //若有产品已上架到es，则清除es已上架产品
        GoodsDeleteVo goodsDeleteVo = new GoodsDeleteVo();
        goodsDeleteVo.setSpuId(goodsEntity.getSpuId());
        searchFeignService.productDelete(goodsDeleteVo).valid();

    }

    @Override
    public FreightQueryPrice countWeightVolume(List<GoodSkuBuyDetail> list) {
        FreightQueryPrice queryPrice = new FreightQueryPrice();
        List<CommodityGoodsEntity> goods = commodityGoodsService.listByIds(list.stream().map(GoodSkuBuyDetail::getSpuId).collect(Collectors.toList()));
        BigDecimal totalVolume = BigDecimal.ZERO;
        BigDecimal totalWeight = BigDecimal.ZERO;
        for (CommodityGoodsEntity good : goods) {
            for (GoodSkuBuyDetail detail : list) {
                if (Objects.equals(detail.getSpuId(), good.getId())) {
                    totalVolume = totalVolume.add(good.getWidth().multiply(good.getLength()).multiply(BigDecimal.valueOf(detail.getSkuQuantity())).setScale(2, RoundingMode.HALF_UP));
                    totalWeight = totalWeight.add(good.getGrossWeight().setScale(2, RoundingMode.HALF_UP));
                }
            }
        }
        queryPrice.setVolume(totalVolume);
        queryPrice.setWeight(totalWeight);
        return queryPrice;
    }

    private CommodityGoodsEntity getGoodsEntity(GoodSpuVo vo) {
        CommodityGoodsEntity goods = new CommodityGoodsEntity();
        goods.setName(vo.getName());
        goods.setSubName(vo.getSubName());
        goods.setCategoryId(vo.getCategoryId());
        goods.setBrandId(vo.getBrandId());
        goods.setGrossWeight(vo.getGrossWeight());
        goods.setLength(vo.getLength());
        goods.setWidth(vo.getWidth());
        goods.setHeight(vo.getHeight());
        goods.setStatus(ProductStatusEnum.PRODUCT_AUDIT.getCode());
        return goods;
    }

}
